package com.stm.bi.report;


import com.stm.base.dto.vo.DictVO;
import com.stm.base.provider.DictionaryProvider;
import com.stm.bi.core.util.DateUtils;
import com.stm.bi.core.util.SqlUtils;
import com.stm.bi.dto.query.DeptSalesTrendChartQry;
import com.stm.bi.dto.query.DimensionDataGroupQry;
import com.stm.bi.model.Chart;
import com.stm.bi.model.DateRange;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.dto.Response;
import com.stm.saas.api.ProductConfigRemoteService;
import com.stm.saas.constant.DictionaryConstants;
import com.stm.saas.dto.vo.ProductConfigVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static com.stm.bi.constant.PlanConstants.TYPE_MONTH;
import static com.stm.saas.constant.IndexConstants.DATE_FIELD_NAME;

@Component
public class DeptSalesTrendQueryExe extends AbsChartQueryExe<DeptSalesTrendChartQry, Chart> {

    @Resource
    private DictionaryProvider dictionaryProvider;
    @Resource
    private ProductConfigRemoteService productConfigRemoteService;

    @Override
    public Chart query(Long orgId, String orgNo, DeptSalesTrendChartQry query) {
        DimensionDataGroupQry qry = new DimensionDataGroupQry();

        String date;
        if (query.getDate() != null) {
            date = query.getDate();
        } else {
            date = DateUtils.getCycMonth(DateUtils.getCurrentDate(), 1);
        }

        String currentDate = DateUtils.getCurrentDate();
        DateRange monthDf = DateUtils.getMonthFirstAndEnd(date, 1);
        String endDate;
        if (Objects.equals(date, DateUtils.getCycMonth(currentDate, 1))) {
            endDate = currentDate;
        } else {
            endDate = monthDf.getEndDate();
        }

        if (query.getDeptId() == null) {
            qry.setDeptId(UserHolder.getLoginUser().getDeptId());
        }else {
            qry.setDeptId(query.getDeptId());
        }

        Response<ProductConfigVO> prodResp = productConfigRemoteService.selectByOrgId(UserHolder.getOrgId());
        if(!prodResp.isSuccess()){
            log.error("销售额配置查询失败,详情=>{}", prodResp.getMessage());
        }
        ProductConfigVO prodConfig = prodResp.getData();
        String salesType;
        if(prodConfig != null && prodConfig.getSalesDefinition() != null){
            salesType = prodConfig.getSalesDefinition();
        } else {
            salesType = "dealing";
        }

        List<String> dateList = DateUtils.getDateList(monthDf.getStartDate(), endDate, "day");

        qry.setStartDate(monthDf.getStartDate())
                .setEndDate(endDate)
                .setDateType("day")
                .setSalesType(salesType);

        Chart chart = new Chart();
        if(query.getType().equals("0")){
            chart = getLineChartByIndex(qry, dateList);
        }else if(query.getType().equals("1")){
            chart = getLineChartByIndices(qry, dateList);
        }

        return chart;
    }

    /**
     * 获取折线图数据
     *
     * @param qry            实绩请求类
     * @param dateList       坐标范围
     * @return ChartDataVO
     */
    public Chart getLineChartByIndex(DimensionDataGroupQry qry, List<String> dateList) {

        Chart chart = new Chart();

        List<DictVO> salesTypes = dictionaryProvider.selectList(DictionaryConstants.PRODUCT_CONFIG_SALES_DEFINITION);
        Map<String,List<Map>> resMap = new HashMap<>();

        salesTypes.removeIf(s -> s.getValue().equals(qry.getSalesType()));
        DictVO dict = new DictVO();
        dict.setValue(qry.getSalesType())
                .setLabel("销售额");
        salesTypes.add(0, dict);

        String salesType = qry.getSalesType();
        for(DictVO type: salesTypes){
            qry.setSalesType(type.getValue());
            String sql = SqlUtils.buildSql(qry, "ads_base_default_sales");
            List<Map> list = jdbcService.selectList(sql, new Object[]{});
            list.sort(Comparator.comparing((Map m) -> ((String) m.get(DATE_FIELD_NAME))));
            resMap.put(type.getValue(), list);

            if(salesType.equals(type.getValue())){
                chart.getItems().add("销售额");
            }else {
                chart.getItems().add(type.getLabel() + "销额");
            }

        }


        List<List<Object>> datas = new ArrayList<>();
        for (String d : dateList) {
            List<Object> data = new ArrayList<>();
            String dateName;
            if (TYPE_MONTH.equals(qry.getDateType()) && dateList.size() > 12) {
                dateName = DateUtils.getName(d);
            } else {
                dateName = DateUtils.getNameByCycle(d, qry.getDateType());
            }

            data.add(dateName);

            for (DictVO type: salesTypes){
                List<Map> list = resMap.get(type.getValue());
                if (list.isEmpty()) {
                    data.add(BigDecimal.valueOf(0).setScale(2, RoundingMode.HALF_UP));
                } else {
                    Map map = list.stream()
                            .filter(m -> Objects.equals(m.get(DATE_FIELD_NAME).toString(), d))
                            .findAny().orElse(new HashMap());
                    if (!map.isEmpty()) {
                        data.add((map.get("sales_amount") == null ? BigDecimal.ZERO : (BigDecimal) map.get("sales_amount")).setScale(2, RoundingMode.HALF_UP));
                    } else {
                        data.add(BigDecimal.valueOf(0).setScale(2, RoundingMode.HALF_UP));
                    }
                }
            }
            datas.add(data);

        }

        chart.setDatas(datas);
        return chart;
    }

    /**
     * 获取折线图数据
     *
     * @param qry            实绩请求类
     * @param dateList       坐标范围
     * @return ChartDataVO
     */
    public Chart getLineChartByIndices(DimensionDataGroupQry qry, List<String> dateList) {

        String sql = SqlUtils.buildSql(qry, "ads_base_default_sales");

        List<Map> list = jdbcService.selectList(sql, new Object[]{});

        List<String> fieldNames = List.of("sales_amount", "return_amount");

        list.sort(Comparator.comparing((Map m) -> ((String) m.get(DATE_FIELD_NAME))));

        Chart chart = new Chart();
        chart.getItems().add("销售额");
        if("delivery".equals(qry.getSalesType())){
            chart.getItems().add("退货额");
        }else {
            chart.getItems().add("退单额");
        }

        List<List<Object>> datas = new ArrayList<>();
        for (String d : dateList) {
            String dateName;
            if (TYPE_MONTH.equals(qry.getDateType()) && dateList.size() > 12) {
                dateName = DateUtils.getName(d);
            } else {
                dateName = DateUtils.getNameByCycle(d, qry.getDateType());
            }
            if (list.isEmpty()) {
                datas.add(Arrays.asList(dateName, BigDecimal.valueOf(0), BigDecimal.valueOf(0)));
            } else {
                List data = new ArrayList();
                data.add(dateName);
                for(String fieldName : fieldNames){
                    Map map = list.stream()
                            .filter(m -> Objects.equals(m.get(DATE_FIELD_NAME).toString(), d))
                            .findAny().orElse(new HashMap());

                    if (!map.isEmpty()) {
                        BigDecimal value = (map.get(fieldName) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) map.get(fieldName)).setScale(2, RoundingMode.HALF_UP);
                        if("return_amount".equals(fieldName)){
                            value = value.divide(BigDecimal.valueOf(-1), 2, RoundingMode.HALF_UP);
                        }
                        data.add(value);
                    } else {
                        data.add(BigDecimal.valueOf(0));
                    }
                }
                datas.add(data);
            }
        }

        chart.setDatas(datas);
        return chart;
    }


    @Override
    public String getReportName() {
        return null;
    }
}
